using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.FileProviders;
using Microsoft.OpenApi.Models;

namespace AppDown;

public class Program
{
    public static void Main(string[] args)
    {
        var builder = WebApplication.CreateBuilder(args);

        // Add services to the container.

        builder.Services.AddControllers();
        // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
        builder.Services.AddEndpointsApiExplorer();

        //开启目录浏览服务
        builder.Services.AddDirectoryBrowser();

        builder.Services.AddControllers()
        .AddJsonOptions(options =>
        {
            //避免在序列化对象时陷入无限循环，如果这样了这个配置就直接不鸟它
            options.JsonSerializerOptions.ReferenceHandler = System.Text.Json.Serialization.ReferenceHandler.IgnoreCycles;
            //默认就是转换为小驼峰式命名规则，设为null 就是保留原来格式
            options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
            //将对象序列化为 JSON 字符串时，将使用缩进格式来使生成的 JSON 字符串更易读
            options.JsonSerializerOptions.WriteIndented = true;
            /*
             * 本意：如果该值为 null，则在序列化过程中该属性将被忽略，仅适用于引用类型属性和字段
             * 和之前的 就是之前的 IgnoreNullValues = true; 一个意思
             */
            options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
            //在序列化和反序列化枚举类型时使用字符串表示
            options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
            //大小写敏感
            options.JsonSerializerOptions.PropertyNameCaseInsensitive = false;
            //在将字典序列化为 JSON 字符串时，字典键的名称将使用驼峰命名法
            options.JsonSerializerOptions.DictionaryKeyPolicy = JsonNamingPolicy.CamelCase;
            //禁止在生成的 JSON 字符串中包含尾随逗号
            options.JsonSerializerOptions.AllowTrailingCommas = false;
            //禁止在 JSON 字符串中包含注释
            options.JsonSerializerOptions.ReadCommentHandling = JsonCommentHandling.Disallow;
            //设置JSON序列化器的最大嵌套深度为 0 （防止恶意攻击，往你json里面塞进去几个G的字符串）
            options.JsonSerializerOptions.MaxDepth = 0;
        });

        // 添加Swagger服务
        builder.Services.AddSwaggerGen(options =>
        {
            options.SwaggerDoc("v1", new OpenApiInfo
            {
                Title = " AppDownload API",
                Version = "V1",
                Description = "App 下载",

            });

            // 获取xml文件名
            var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
            // 获取xml文件路径
            var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
            // 添加控制器层注释，true表示显示控制器注释
            options.IncludeXmlComments(xmlPath, true);
            // 对action的名称进行排序，如果有多个，就可以看见效果了
            options.OrderActionsBy(o => o.RelativePath);
        });

        // Cros 跨域配置 第1步 
        // 定义允许跨域请求的URL数组
        string[] urls = new[] { "http://127.0.0.1:5500", "http://localhost:5501" };
        // 向依赖注入容器中添加跨域服务，并配置默认的跨域策略
        builder.Services.AddCors(options =>
            options.AddDefaultPolicy(builder =>
                // 配置跨域策略，允许指定来源的请求
                builder.WithOrigins(urls)
                // 允许任何请求方法
                .AllowAnyMethod()
                // 允许任何请求头
                .AllowAnyHeader()
                // 允许请求携带凭证（如cookies）
                .AllowCredentials()
            )
        );

        //内存缓存
        builder.Services.AddMemoryCache();
        //控制器
        builder.Services.AddControllers();
        //限制文件上传大小
        builder.Services.Configure<FormOptions>(options =>
        {
            // 设置上传大小限制256MB
            options.MultipartBodyLengthLimit = 268435456;

        });

        var app = builder.Build();

        // Configure the HTTP request pipeline.
        if (app.Environment.IsDevelopment())
        {
            app.UseSwagger();
            app.UseSwaggerUI();
        }

        // 使用HTTPS重定向中间件，将所有HTTP请求重定向到HTTPS。
        app.UseHttpsRedirection();

        // 使用静态文件中间件来处理应用中的静态文件。
        app.UseStaticFiles();

        // 创建一个物理文件提供者，用于提供位于"app"子目录下的静态文件。
        var fileProvider = new PhysicalFileProvider(Path.Combine(builder.Environment.WebRootPath, "app"));
        var requestPath = "/app";

        // 设置自定义内容类型 - 将文件扩展名关联到MIME类型
        var provider = new FileExtensionContentTypeProvider();
        // 添加 apk 格式的映射
        provider.Mappings[".apk"] = "application/x-msdownload";
        // 使用静态文件中间件来处理静态文件，此处配置了自定义的内容类型提供者。
        app.UseStaticFiles(new StaticFileOptions
        {
            ContentTypeProvider = provider
        });
        // 启用浏览器链接的显示。
        app.UseStaticFiles(new StaticFileOptions
        {
            FileProvider = fileProvider,
            RequestPath = requestPath
        });

        // 使用目录浏览中间件，允许用户通过浏览器查看目录结构。
        app.UseDirectoryBrowser(new DirectoryBrowserOptions
        {
            FileProvider = fileProvider,
            RequestPath = requestPath
        });

        // Cros 跨域配置 第2步 使用跨源资源共享 (CORS) 中间件
        app.UseCors();

        app.UseAuthorization();

        app.MapControllers();

        app.Run();
    }
}